home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / nasanets.zip / LAYER.C < prev    next >
C/C++ Source or Header  |  1990-06-07  |  19KB  |  514 lines

  1. /*=============================*/
  2. /*           NETS              */
  3. /*                             */
  4. /* a product of the AI Section */
  5. /* NASA, Johnson Space Center  */
  6. /*                             */
  7. /* principal author:           */
  8. /*       Paul Baffes           */
  9. /*                             */
  10. /* contributing authors:       */
  11. /*      Bryan Dulock           */
  12. /*      Chris Ortiz            */
  13. /*=============================*/
  14.  
  15.  
  16. /*
  17. ----------------------------------------------------------------------
  18.   Code For Manipulating Layer And Layer_lst Structures (Prefix = L_)
  19. ----------------------------------------------------------------------
  20.   This code is divided into 2 major sections:
  21.  
  22.   (1) include files
  23.   (2) subroutines
  24.  
  25.   Each section is further explained below.
  26. ----------------------------------------------------------------------
  27. */
  28.  
  29.  
  30. /*
  31. ----------------------------------------------------------------------
  32.   INCLUDE FILES
  33. ----------------------------------------------------------------------
  34. */
  35. #include  "common.h"
  36. #include  "weights.h"
  37. #include  "layer.h"
  38. #include  "netio.h"
  39.  
  40.  
  41. /*
  42. ----------------------------------------------------------------------
  43.   EXTERNED ROUTINES AND GLOBALS
  44. ----------------------------------------------------------------------
  45. */
  46. extern void    W_free_weights_lst();
  47. extern float   C_Sint_to_float();
  48. extern D_Sint  LR_calc_learn_rate();
  49. extern float   LR_scale_default();
  50. extern char    *sys_alloc();
  51. extern void    sys_free();
  52. extern void    IO_print();
  53. extern int     IO_more();
  54. extern float   IO_get_default_float();
  55. extern void    IO_insert_format();
  56.  
  57. extern char    IO_wkstr[MAX_LINE_SIZE];
  58. extern char    IO_str[MAX_LINE_SIZE];
  59.  
  60.  
  61. /*
  62. ======================================================================
  63.   ROUTINES IN LAYER.C                                                   
  64. ======================================================================
  65.   The routines in this file are grouped below by function.  Each routine
  66.   is prefixed by the string "L_" indicating that it is defined in the 
  67.   "layer.c" file.  The types returned by the routines are also shown here
  68.   so that cross checking is more easily done between these functions
  69.   and the other files which intern them.
  70.  
  71.  
  72.   Type Returned                 Routine                                 
  73.   -------------                 -------                                 
  74.                                                                       
  75.   LAYER ROUTINES                                             
  76.     Layer *                     L_alloc_layer
  77.     Weights *                   L_get_weights
  78.     void                        L_free_layer
  79.     void                        L_update_learn_rates
  80.     void                        L_modify_learning
  81.     void                        L_show_biases
  82.     void                        L_show_learn_rates
  83.                                                                       
  84.   LAYER_LST ROUTINES                                                    
  85.     Layer_lst *                 L_alloc_layer_lst
  86.     Layer_lst *                 L_insert_before
  87.     Layer_lst *                 L_insert_after
  88.     void                        L_free_layer_lst
  89. ======================================================================
  90. */
  91.  
  92.  
  93. Layer  *L_alloc_layer(ptr_spec)
  94. Layer_spec  *ptr_spec;
  95. /*
  96. ----------------------------------------------------------------------
  97.  Given a number of nodes for the layer, this routine creates a Layer  
  98.   structure and mallocs enough space for the 'outputs' and 'deltas'   
  99.   arrays.  Note, however, that the pointers to the weights are NOT    
  100.   filled in at this time.  That is done later, after all other layers 
  101.   and weights have been created.                                      
  102.  This routine also takes the time to reset all of the output and      
  103.   delta values to 0.  Of course, this could be changed to a random    
  104.   number.                                                             
  105. ----------------------------------------------------------------------
  106. */
  107. BEGIN
  108.    int           i, nodes;
  109.    unsigned int  size;
  110.    Layer         *result;
  111.  
  112.    /*-----------------------------------------*/
  113.    /* set up a temporary variable holding the */
  114.    /* number of nodes for multiple accesses   */
  115.    /*-----------------------------------------*/
  116.    nodes = ptr_spec->num_nodes;
  117.    
  118.    result = (Layer *) sys_alloc((unsigned)sizeof(Layer));
  119.    result->ID           = ptr_spec->ID;
  120.    result->num_nodes    = nodes;
  121.    result->max_incoming = 0;
  122.    result->X_dim        = ptr_spec->X_dim;
  123.    result->Y_dim        = ptr_spec->Y_dim;
  124.    result->cur_learn    = 0;
  125.    result->learn_base   = ptr_spec->learn_base;
  126.    result->learn_scale  = ptr_spec->learn_scale;
  127.    result->momentum     = ptr_spec->momentum;
  128.    size = ((unsigned) nodes) * ((unsigned) sizeof(Sint));
  129.    result->node_outputs = (Sint *) sys_alloc(size);
  130.    result->node_deltas  = (Sint *) sys_alloc(size);
  131.    result->node_bias    = (Sint *) sys_alloc(size);
  132.    result->prev_deltaB  = (Sint *) sys_alloc(size);
  133.    for (i = 0; i < nodes; i++) BEGIN
  134.       result->node_outputs[i] = 0;
  135.       result->node_deltas[i]  = 0;
  136.       result->node_bias[i]    = 0;
  137.       result->prev_deltaB[i]  = 0;
  138.    ENDFOR
  139.    result->in_weights   = NULL;
  140.    result->out_weights  = NULL;
  141.  
  142.    return(result);
  143.  
  144. END /* L_alloc_layer */
  145.  
  146.  
  147. void  L_free_layer(ptr_layer)
  148. Layer  *ptr_layer;
  149. /*
  150. ----------------------------------------------------------------------
  151.   This routine frees the space associated with a layer structure and 
  152.    any of the space associated with its INCOMING weights. Only the 
  153.    incoming weights are addressed as each weight structure has two 
  154.    references so only one need be used (both is redundant). Note that
  155.    the Layer_lst structures are freed by the CALLER of this routine. 
  156.    That is, an assumption is made that whomever is cleaning up takes
  157.    the responsibility of removing the layer list.
  158. ----------------------------------------------------------------------
  159. */
  160. BEGIN
  161.    Weights_lst  *cur, *last;
  162.    
  163.    if (ptr_layer == NULL) return;
  164.    
  165.    /*-----------------------------------*/
  166.    /* free the actual node value arrays */
  167.    /*-----------------------------------*/
  168.    sys_free((char *) ptr_layer->node_outputs);
  169.    sys_free((char *) ptr_layer->node_deltas);
  170.    sys_free((char *) ptr_layer->node_bias);
  171.    sys_free((char *) ptr_layer->prev_deltaB);
  172.  
  173.    /*---------------------------------*/
  174.    /* free the incoming weight arrays */
  175.    /*---------------------------------*/
  176.    W_free_weights_lst(ptr_layer->in_weights);
  177.    
  178.    /*------------------------------------*/
  179.    /* loop through the outgoing weights  */
  180.    /* freeing JUST WEIGHT_LST structures */
  181.    /*------------------------------------*/
  182.    cur = ptr_layer->out_weights;
  183.    while (cur != NULL) BEGIN
  184.       last = cur;
  185.       cur = cur->next;
  186.       sys_free((char *) last);
  187.    ENDWHILE
  188.    
  189.    sys_free((char *) ptr_layer);
  190.  
  191. END /* L_free_layer */
  192.  
  193.  
  194. Layer_lst  *L_alloc_layer_lst(ptr_layer)
  195. Layer  *ptr_layer;
  196. /*
  197. ----------------------------------------------------------------------
  198.  Given a pointer to a Layer structure, this routine allocates enough  
  199.   space for a Layer_lst structure and initialized the 'value' field   
  200.   to point to 'ptr_layer'.  As above, by returning a pointer to the   
  201.   malloc'ed space, the allocation remains after this routine returns. 
  202. ----------------------------------------------------------------------
  203. */
  204. BEGIN
  205.    Layer_lst  *result;
  206.  
  207.    result = (Layer_lst *) sys_alloc((unsigned) sizeof(Layer_lst));
  208.    result->value = ptr_layer;
  209.    result->prev  = NULL;
  210.    result->next  = NULL;
  211.  
  212.    return(result);
  213.  
  214. END /* L_alloc_layer_lst */
  215.  
  216.  
  217. Layer_lst  *L_insert_before(ptr_node, ptr_lst)
  218. Layer_lst  *ptr_node, *ptr_lst;
  219. /*
  220. ----------------------------------------------------------------------
  221.  The inputs to this routine are both pointers to Layer_lst structures 
  222.   The first should be a pointer to a NEW element to be added to the   
  223.   list of Layer_lst structures, which are pointed to by the second    
  224.   argument.  Additionally, the second argument is assumed to point to 
  225.   an element in the list BEFORE WHICH the new node is to be put.      
  226.  Note that the Layer_lst structured form a DOUBLY linked list, so     
  227.   both previous ('prev') and next ('next') pointers must be set up    
  228.   here.                                                               
  229.  Finally, note that there can be some confusion as to what value to   
  230.   return from this routine.  Think of it this way: say you had a list 
  231.   (x y z) and you wanted to add element Q to the list.  The result in 
  232.   this routine would be (Q x y z); thus you would want the pointer    
  233.   returned from this routine to be the POINTER TO THE INSERTED        
  234.   ELEMENT.  If, however, one of the arguments were NULL, then you     
  235.   would always want to return the other argument.  This takes care of 
  236.   the case when you insert an element into an empty list.             
  237.  As a result, when using this routine you should ALWAYS reassign the  
  238.   value of you list to the output returned here.  Otherwise, the NULL 
  239.   cases will not be handled properly.                                 
  240. ----------------------------------------------------------------------
  241. */
  242. BEGIN
  243.    if (ptr_node == NULL)
  244.       return(ptr_lst);
  245.    else if (ptr_lst == NULL)
  246.       return(ptr_node);
  247.    else BEGIN
  248.       ptr_node->prev = ptr_lst->prev;      /* set up new node pointers */
  249.       ptr_node->next = ptr_lst;
  250.  
  251.       if (ptr_node->prev != NULL)          /* reset prev node next ptr */
  252.          ptr_node->prev->next = ptr_node;  /* if there is a prev node  */
  253.  
  254.       ptr_node->next->prev = ptr_node;     /* reset next node prev ptr */
  255.       return(ptr_node);                    /* return ptr to new node   */
  256.    ENDELSE
  257.  
  258. END /* L_insert_before */
  259.  
  260.  
  261. Layer_lst  *L_insert_after(ptr_node, ptr_lst)
  262. Layer_lst  *ptr_node, *ptr_lst;
  263. /*
  264. ----------------------------------------------------------------------
  265.  The inputs to this routine are both pointers to Layer_lst structures 
  266.   The first should be a pointer to a new element to be added to the   
  267.   list of Layer_lst structures, which are pointed to by the second    
  268.   argument.  Additionally, the second argument is assumed to point to 
  269.   an element in the list AFTER WHICH the new node is to be put.       
  270.  Note that the Layer_lst structured form a DOUBLY linked list, so     
  271.   both previous ('prev') and next ('next') pointers must be set up    
  272.   here.                                                               
  273.  Like the above routine, this guy should always be used to reset the  
  274.   the value of the original list pointer, because of the differences  
  275.   between NULL cases and the normal case.  However, unlike the routine
  276.   above, this routine returns a pointer to the OLD list, not the newly
  277.   inserted node.  That is, if you want Q to be inserted after your    
  278.   pointer to (x y z), then you want (x Q y z) as your result, not     
  279.   (Q y z)!                                                            
  280. ----------------------------------------------------------------------
  281. */
  282. BEGIN
  283.    if (ptr_node == NULL)
  284.       return(ptr_lst);
  285.    else if (ptr_lst == NULL)
  286.       return(ptr_node);
  287.    else BEGIN
  288.       ptr_node->prev = ptr_lst;            /* set up new node pointers */
  289.       ptr_node->next = ptr_lst->next;
  290.  
  291.       ptr_node->prev->next = ptr_node;     /* reset prev node next ptr */
  292.  
  293.       if (ptr_node->next != NULL)          /* reset next node prev ptr */
  294.          ptr_node->next->prev = ptr_node;  /* if there is a next node  */
  295.       return(ptr_lst);                     /* return ptr to list       */
  296.    ENDELSE
  297.  
  298. END /* L_insert_after */
  299.  
  300.  
  301. void  L_free_layer_lst(ptr_lst)
  302. Layer_lst  *ptr_lst;
  303. /*
  304. ----------------------------------------------------------------------
  305.   Loops through a layer list linked list freeing layers as it goes.
  306.    Each layers must also have its corresponding layer_lst structure 
  307.    freed. Note that the layers free weights, but only the INCOMING 
  308.    weights since each weight structure is doubly referenced.
  309.   NOTE THAT THE INCOMING POINTER IS DESTROYED by the operations in this
  310.    routine.
  311. ----------------------------------------------------------------------
  312. */
  313. BEGIN
  314.    Layer_lst  *last_layer;
  315.    void        L_free_layer();
  316.   
  317.    if (ptr_lst == NULL) return;
  318.    
  319.    /*-------------------------------------*/
  320.    /* loop through the layer list freeing */
  321.    /* layers (and thus weights). Also be  */
  322.    /* sure to free layer_lst pointers.    */
  323.    /*-------------------------------------*/
  324.    while (ptr_lst != NULL) BEGIN
  325.    
  326.       /*---------------------------------------*/
  327.       /* free current layer and its IN weights */
  328.       /*---------------------------------------*/
  329.       L_free_layer(ptr_lst->value);
  330.       
  331.       /*-------------------------------*/
  332.       /* then free layer_lst structure */
  333.       /*-------------------------------*/
  334.       last_layer = ptr_lst;
  335.       ptr_lst = ptr_lst->next;
  336.       sys_free((char *) last_layer);
  337.    ENDWHILE
  338.    
  339. END /* L_free_layer_lst */
  340.  
  341.  
  342. Weights  *L_get_weights(ptr_layer, target)
  343. Layer  *ptr_layer;
  344. int    target;
  345. /*
  346. ----------------------------------------------------------------------
  347.  This routine attempts to return a pointer to a Weights structure     
  348.   given the assumption that the input 'ptr_layer' is a pointer to the 
  349.   layer which is the "source" for the Weights structure, and the      
  350.   'target' input parameter is a number representing the ID of the     
  351.   target layer.  If no such target layer is found, then a dummy       
  352.   Weights structure is returned with -1 as the value for the target   
  353.   size, indicating that no such set of weights exists.                
  354.  The mechanics of the routine are not hard.  All that need be done is 
  355.   to make a search through the OUT weights list for a Weights struct  
  356.   which has 'target' as the ID of its target layer.                   
  357. ----------------------------------------------------------------------
  358. */
  359. BEGIN
  360.    Weights_lst  *ptr_weights_lst;
  361.    Weights      *dummy;
  362.  
  363.    ptr_weights_lst = ptr_layer->out_weights;
  364.    while (ptr_weights_lst != NULL) BEGIN
  365.       if (ptr_weights_lst->value->target_layer->ID == target)
  366.          return(ptr_weights_lst->value);
  367.       ptr_weights_lst = ptr_weights_lst->next;
  368.    ENDWHILE
  369.  
  370.    dummy = (Weights *) sys_alloc((unsigned) sizeof(Weights));
  371.    dummy->type = ERROR;
  372.    return(dummy);
  373.  
  374. END /* L_get_weights */
  375.  
  376.  
  377. void  L_update_learn_rates(ptr_layers, avg_err)
  378. Layer_lst  *ptr_layers;
  379. Sint       avg_err;
  380. /*
  381. ----------------------------------------------------------------------
  382.   Given an input to the hidden_front list of layers (see net.h) this 
  383.   routine computes the new learning rates for each layer of the network
  384.   except the input layer (the input layer has no learning rate).
  385. ----------------------------------------------------------------------
  386. */
  387. BEGIN
  388.    Layer  *cur_layer;
  389.    
  390.    while(ptr_layers != NULL) BEGIN
  391.       cur_layer = ptr_layers->value;
  392.       /*-----------------------------------*/
  393.       /* if scale == 0, then it is assumed */
  394.       /* that the learning rate stays same */
  395.       /*-----------------------------------*/
  396.       if (cur_layer->learn_scale != 0.0)
  397.          cur_layer->cur_learn = 
  398.             LR_calc_learn_rate(cur_layer->learn_base, cur_layer->learn_scale,
  399.                                avg_err);
  400.       ptr_layers = ptr_layers->next;
  401.    ENDWHILE
  402.  
  403. END /* L_update_learn_rates */
  404.  
  405.  
  406. void  L_modify_learning(layer_num, ptr_layer)
  407. int    layer_num;
  408. Layer  *ptr_layer;
  409. /*
  410. ----------------------------------------------------------------------
  411.   Prompts the user for new learning rate, scaling, and momentum 
  412.   values.
  413. ----------------------------------------------------------------------
  414. */
  415. BEGIN
  416.    float  temp_scale;
  417.    
  418.    if (ptr_layer->ID == ERROR) BEGIN
  419.       sprintf(IO_str, "\n*** layer %d does not exist ***", layer_num);
  420.       IO_print(0);
  421.    ENDIF
  422.    else if (layer_num < 1) BEGIN
  423.       sprintf(IO_str, "\n*** no learning rate associate with layer %d ***", layer_num);
  424.       IO_print(0);
  425.    ENDIF
  426.    else BEGIN
  427.       sprintf(IO_str, "\n     Enter learning rate for layer %d", layer_num);
  428.       IO_print(0);
  429.       sprintf(IO_wkstr, " (default=%%.f): ");
  430.       IO_insert_format(IO_wkstr);
  431.       sprintf(IO_str, IO_wkstr, ptr_layer->learn_base);
  432.       IO_print(0);
  433.       ptr_layer->learn_base = IO_get_default_float(ptr_layer->learn_base);
  434.  
  435.       temp_scale = LR_scale_default(ptr_layer->learn_base);
  436.       sprintf(IO_str, "\n     Enter scaling factor or 0 if not desired");
  437.       IO_print(0);
  438.       sprintf(IO_wkstr, " (default=%%.f): ");
  439.       IO_insert_format(IO_wkstr);
  440.       sprintf(IO_str, IO_wkstr, temp_scale);
  441.       IO_print(0);
  442.       ptr_layer->learn_scale = IO_get_default_float(temp_scale);
  443.      
  444.       sprintf(IO_str, "\n     Enter momentum for layer %d", layer_num);
  445.       IO_print(0);
  446.       sprintf(IO_wkstr, " (default=%%.f): ");
  447.       IO_insert_format(IO_wkstr);
  448.       sprintf(IO_str, IO_wkstr, ptr_layer->momentum);
  449.       IO_print(0);
  450.       ptr_layer->momentum = IO_get_default_float(ptr_layer->momentum);      
  451.    ENDELSE
  452.  
  453. END /* L_modify_learning */
  454.  
  455.  
  456. void  L_show_biases(ptr_layer)
  457. Layer  *ptr_layer;
  458. /*
  459. ----------------------------------------------------------------------
  460.  Given a pointer to a layer, this routine prints out all the bias values
  461.   associated with that layer.
  462. ----------------------------------------------------------------------
  463. */
  464. BEGIN
  465.    int    i;
  466.    float  t1;
  467.    Sint   *bias_values;
  468.    
  469.    bias_values = ptr_layer->node_bias;
  470.    for (i = 0; i < ptr_layer->num_nodes; i++) BEGIN
  471.       t1 = C_Sint_to_float(bias_values[i]);
  472.       sprintf(IO_wkstr, "bias %d = %%.f  ", i);
  473.       IO_insert_format(IO_wkstr);
  474.       sprintf(IO_str, IO_wkstr, t1);
  475.       if (IO_more (0) == ERROR) return;
  476.       if ((i+1) % 3 == 0) BEGIN
  477.          sprintf(IO_str, "\n");
  478.          if (IO_more (0) == ERROR) return;
  479.       ENDIF
  480.    ENDFOR
  481.    sprintf(IO_str, "\n\n");
  482.    if (IO_more (0) == ERROR) return;
  483.    
  484. END /* L_show_biases */
  485.  
  486.  
  487. void  L_show_learn_rates(ptr_layer)
  488. Layer  *ptr_layer;
  489. /*
  490. ----------------------------------------------------------------------
  491.   Given a pointer to a layer, this routine prints out the learning rate
  492.   momentum and scale factors for that layer.
  493. ----------------------------------------------------------------------
  494. */
  495. BEGIN
  496.    sprintf(IO_str, "\nLayer %d", ptr_layer->ID);
  497.    IO_print(0);
  498.    sprintf(IO_wkstr, "\n   Base learning rate    :%%.f");
  499.    IO_insert_format(IO_wkstr);
  500.    sprintf(IO_str, IO_wkstr, ptr_layer->learn_base);
  501.    IO_print(0);
  502.    if (ptr_layer->learn_scale != 0) BEGIN
  503.       sprintf(IO_wkstr, "\n   Scaling factor        :%%.f");
  504.       IO_insert_format(IO_wkstr);
  505.       sprintf(IO_str, IO_wkstr, ptr_layer->learn_scale);
  506.       IO_print(0);
  507.    ENDIF
  508.    sprintf(IO_wkstr, "\n   Delta weight constant :%%.f\n");
  509.    IO_insert_format(IO_wkstr);
  510.    sprintf(IO_str, IO_wkstr, ptr_layer->momentum);
  511.    IO_print(0);
  512.    
  513. END /* L_show_learn_rates */
  514.